/*
 * Copyright (C) 2011, EADS France
 * 
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 */
package xowl.gmi.controller;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 *
 * @author Laurent WOUTERS
 */
public class LibraryElement extends xowl.gmi.view.ToolboxElementDragable {
    private static final String defaultValue = "<unnamed>";
    private String defaultName;
    private Map<xowl.gmi.model.ast.StringToken, xowl.interpreter.adapter.DataPropertyObserver> observers;
    private List<String> parts;
    
    public LibraryElement(final xowl.gmi.model.ast.ASTNode node, xowl.gmi.view.ViewStyle style) {
        super(new xowl.gmi.view.ToolboxElementDragable.Actions() {
            @Override public java.awt.datatransfer.DataFlavor getFlavor() { return Controller.flavorASTNode; }
            @Override public Object getData() { return node; }
        }, "", style);
        defaultName = node.getIRIString().split("#")[1];
        observers = new HashMap<>();
        parts = new ArrayList<>();
        for (xowl.gmi.model.ast.StringToken token : getStringTokens(node))
            addObserver(token);
        resetName();
    }
    
    private Collection<xowl.gmi.model.ast.StringToken> getStringTokens(xowl.gmi.model.ast.ASTNode node) {
        // node ?route ?n
        // ?n meta:token ?t
        // ?t is view:StringToken
        xowl.interpreter.Repository repository = node.getRepository();
        Collection<xowl.gmi.model.ast.StringToken> result = new ArrayList<>();
        xowl.lang.actions.QueryVariable r = new xowl.lang.actions.QueryVariable();
        xowl.lang.actions.QueryVariable n = new xowl.lang.actions.QueryVariable();
        xowl.lang.actions.QueryVariable t = new xowl.lang.actions.QueryVariable();
        r.setName("r");
        n.setName("n");
        t.setName("t");
        xowl.lang.owl2.ObjectPropertyAssertion axiom1 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom1.setIndividual(node.getEntity().getHasIRI());
        axiom1.setObjectProperty(r);
        axiom1.setValueIndividual(n);
        xowl.lang.owl2.ObjectPropertyAssertion axiom2 = new xowl.lang.owl2.ObjectPropertyAssertion();
        axiom2.setIndividual(n);
        axiom2.setObjectProperty(repository.getIRI("http://www.xowl.org/gmi/model/meta#token"));
        axiom2.setValueIndividual(t);
        xowl.lang.owl2.ClassAssertion axiom3 = new xowl.lang.owl2.ClassAssertion();
        axiom3.setIndividual(t);
        axiom3.setClasse(repository.getIRI(xowl.gmi.model.ast.StringToken.getClassIRI()));
        xowl.lang.actions.ValuesOf query = new xowl.lang.actions.ValuesOf();
        query.addAxioms(axiom1);
        query.addAxioms(axiom2);
        query.addAxioms(axiom3);
        query.setOn(t);
        try {
            Collection<xowl.interpreter.QuerySolution> solutions = repository.select(query);
            for (xowl.interpreter.QuerySolution solution : solutions) {
                xowl.lang.runtime.Entity entity = (xowl.lang.runtime.Entity)solution.getValue(t);
                xowl.gmi.model.ast.StringToken token = xowl.gmi.model.ast.StringToken.get(repository, entity);
                if (!result.contains(token))
                    result.add(token);
            }
        }
        catch (xowl.interpreter.XOWLException ex) { }
        return result;
    }
    
    private void addObserver(xowl.gmi.model.ast.StringToken token) {
        String data = token.getDataString();
        data = (data == null ? defaultValue : data);
        final int index = parts.size();
        xowl.interpreter.adapter.DataPropertyObserver obs = new xowl.interpreter.adapter.DataPropertyObserver() {
            @Override public void onAdd(Object elem) {
                parts.set(index, (String)elem);
                resetName();
            }
            @Override public void onRemove(Object elem) {
                parts.set(index, defaultValue);
                resetName();
            }
        };
        observers.put(token, obs);
        parts.add(data);
        token.addPropertyObserver("dataString", obs);
    }
    
    public void onRemove() {
        for (Map.Entry<xowl.gmi.model.ast.StringToken, xowl.interpreter.adapter.DataPropertyObserver> entry : observers.entrySet()) {
            entry.getKey().removePropertyObserver(entry.getValue());
        }
    }
    
    private void resetName() {
        if (parts.isEmpty()) {
            label.setText(defaultName);
        } else {
            java.lang.StringBuilder builder = new java.lang.StringBuilder();
            boolean first = true;
            for (String part : parts) {
                if (!first)
                    builder.append(", ");
                first = false;
                builder.append(part);
            }
            label.setText(builder.toString());
        }
        label.invalidate();
    }
}
